﻿using System.Web;
using AutoTest.Business.IServices.Auth;
using AutoTest.Business.IServices.Common;
using AutoTest.Business.Model;
using AutoTest.Business.Options;
using AutoTest.Business.Services.Common;
using AutoTest.Common;
using AutoTest.Common.Extension;
using AutoTest.Domain;
using Mapster;
using SKIT.FlurlHttpClient.Wechat.Api;
using SKIT.FlurlHttpClient.Wechat.Api.Models;

namespace AutoTest.Business.Services.Auth
{
    /// <summary>
    /// 微信授权相关操作
    /// </summary>
    public class WechatAuthService(ISettingService settintService, IRedisCacheService redisCacheService) : IOpenAuthService
    {
        private readonly ISettingService _settintService = settintService;
        private readonly IRedisCacheService _redisCacheService = redisCacheService;
        private readonly WechatAppOption _wechatAppOption = settintService.GetSettingOptionAsync<WechatAppOption>(AppConsts.APPSETTING_WECHAT_APP).GetAwaiter().GetResult();

        /// <summary>
        /// 获取授权地址
        /// </summary>
        /// <param name="params"></param>
        /// <returns></returns>
        public async Task<string> GetAuthUrlAsync(Dictionary<string, object> @params)
        {
            string auth_url;
            auth_url = _wechatAppOption.WechatAuthUrl;
            if (_wechatAppOption.WechatAuthCallBackUrl.IsNotEmpty()) _wechatAppOption.WechatAuthCallBackUrl = HttpUtility.UrlEncode(_wechatAppOption.WechatAuthCallBackUrl);
            var dict = _wechatAppOption.ToDictionary();
            dict.Add("scope", "snsapi_userinfo");
            auth_url = auth_url.ReplaceForDict(@params.MergeDict(false, dict));
            return await Task.FromResult(auth_url);
        }

        /// <summary>
        /// 获取微信开放平台的用户信息
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public async Task<OpenUserInfoModel> GetOpenUserInfoAsync(string code)
        {
            return await GetOpenUserInfoAsync(await GetAuthAccessTokenAsync(code));
        }

        private WechatApiClient GetWechatApiClient()
        {
            var options = new WechatApiClientOptions()
            {
                AppId = _wechatAppOption.WechatAppId,
                AppSecret = _wechatAppOption.WechatAppSecret,
                PushEncodingAESKey =  _wechatAppOption.WechatEncodingAESKey,
                PushToken = _wechatAppOption.WechatServerToken
            };
            var client = WechatApiClientBuilder.Create(options).Build();
            return client;
        }

        /// <summary>
        ///获取授权的Access_Token
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        private async Task<SnsOAuth2RefreshTokenResponse> GetAuthAccessTokenAsync(string code)
        {
            var client = GetWechatApiClient();
            var tokenResponse = await client.ExecuteSnsOAuth2AccessTokenAsync(new SnsOAuth2AccessTokenRequest() { Code = code });
            return tokenResponse;
        }

        /// <summary>
        /// 获取微信开放平台的用户信息
        /// </summary>
        /// <returns></returns>
        private async Task<OpenUserInfoModel> GetOpenUserInfoAsync(SnsOAuth2RefreshTokenResponse tokenModel)
        {
            string access_token = tokenModel.AccessToken;
            string openid = tokenModel.OpenId;
            if (access_token.IsNotEmpty() && openid.IsNotEmpty())
            {
                var client = GetWechatApiClient();
                var userInfoResponse = await client.ExecuteSnsUserInfoAsync(new SnsUserInfoRequest()
                {
                    AccessToken = access_token,
                    OpenId = openid
                });

                return userInfoResponse.Adapt<OpenUserInfoModel>();
            }
            return null!;

        }

        /// <summary>
        /// 签名检查
        /// </summary>
        /// <param name="signature"></param>
        /// <param name="timestamp"></param>
        /// <param name="nonce"></param>
        /// <param name="echostr"></param>
        /// <returns></returns>
        public string CheckSign(string signature, string timestamp, string nonce, string echostr)
        {
            var client = GetWechatApiClient();
            var result = client.VerifyEventSignatureForEcho(timestamp, nonce, signature);
            return result.Result ? echostr : "false";
        }

        /// <summary>
        /// 获取Access_Token
        /// </summary>
        /// <param name="forcefresh"></param>
        /// <returns></returns>
        public async Task<string> GetWechatAccessTokenStable(bool forcefresh = false)
        {
            var token  = _redisCacheService.Get<string>(AppConsts.REDIS_WECHAT_ACCESS_TOKEN);
            if (token.IsEmpty())
            {
                var client = GetWechatApiClient();
                var tokenResponse = await client.ExecuteCgibinStableTokenAsync(new CgibinStableTokenRequest()
                {
                    AppId = _wechatAppOption.WechatAppId,
                    AppSecret = _wechatAppOption.WechatAppSecret,
                    ForceRefresh = forcefresh,
                    GrantType = "client_credential"
                });
                if (tokenResponse.IsSuccessful())
                {
                    token = tokenResponse.AccessToken;
                    if (token.IsNotEmpty())
                    {
                        _redisCacheService.Set(token, DateTime.Now.AddSeconds(AppConsts.REDIS_WECHAT_ACCESS_TOKEN_EXPIRE_SECONDS));
                    }
                    
                }
            }
           
            return token;
        }
    }
}
